import axios from 'axios'
import { Message, Loading } from 'element-ui'
import store from '@/store'
import router from '@/router'
// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 50000 // 请求超时时间
})

// 设置token有效时长
const time = 24 * 60 * 60 * 1000 // 有效时长1天
let loading
// 请求拦截器
service.interceptors.request.use(config => {
  /**
   * 请求头，请求体，请求行
   * config就是包含 “请求头，请求体，请求行”这3部分的对象
   * */
  // 统一设置token
  const token = store.state.user.token
  // 添加加载效果
  loading = Loading.service({
    lock: true,
    text: 'Loading',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  if (token) {
    // 注意：Bearer后面一定要有空格
    config.headers.Authorization = 'Bearer ' + token

    // 再次获取最新时间戳
    const curTime = Date.now()
    const loginTime = localStorage.getItem('loginTime')
    if ((curTime - loginTime) > time) {
      // token过期了  --
      // 退出登录
      store.dispatch('user/logout')
      // 跳转到登录页面
      router.push('/login')
      // 返回一个错误信息 -- 阻止请求的执行
      // 添加 new Error 的目的：为了 统一再响应拦截器显示错误信息
      // Error会把错误信息包装成一个错误对象，并把传入的错误描述赋值给
      // 错误对象中的message属性
      return Promise.reject(new Error('token过期了，--- 前端设置'))
    }
  }
  return config // 放行
})

// 响应拦截器
// 利用响应拦截器 做统一的错误处理
/**
 * 请求的错误，通常有2种。
 * 情况一：数据层面的错误，比如: 登录接口的账号密码写错导致的错误
 * 情况二：网络层面的错误，比如：我们把登录接口的请求路径写错了
 *
 * */
service.interceptors.response.use((res) => {
  loading.close() // 关闭loading效果
  // console.log('网络层面成功')
  // 后端会返回一个success字段给我们，当这个字段的值为true表示请求成功，false表示请求失败
  const { data, success, message } = res.data
  if (success) {
    // console.log('数据层面成功')
    // 判断获取数据的接口，不需要显示提示
    // console.log(60, res)
    if (res.config.method !== 'get' && res.config.url !== '/api/sys/profile') {
      Message.success(message)
    }
    return data // 解构的目的：是为了简化接口数据的读取
  } else {
    console.log('数据层面失败')
    Message.error(message)
    // Error 原生js的构造函数，用于生产一个错误对象
    // 这里添加new Error 会在控制台打印出来具体报错的位置信息
    return Promise.reject(new Error(message))
  }
}, err => {
  loading.close()// 关闭loading效果
  console.log('网络层面失败：', err)
  console.dir(err)
  // 后端设定的token过期了，调用接口的时候接口会返回一个状态码给我们，
  // 这个状态码就是code，并且值为10002
  if (err.response && err.response.data.code === 10002) {
    // token过期了
    store.dispatch('user/logout')
    // 跳转到登录页面
    router.push('/login')
    Message.error('token超时，--- 后端设置')
    return Promise.reject(err) // 添加这个return是为了 不执行后面提示框
  }
  Message.error(err.message)
  // 返回错误对象给axios，
  // Promise.reject是原生js的一个方法，会返回一个错误对象
  // 最终调用接口时获取到的结果就是这个错误对象
  return Promise.reject(err)
})

export default service
